package com.nav.interpreter.brainfuck;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

public class BrainfuckInterpreter {
	BrainfuckChar code[];
	int codeIndex = 0;
	Ribbon ribbon = new Ribbon();
	Map<Integer, Integer> match = new HashMap<Integer, Integer>();
	public BrainfuckInterpreter(String filePath) throws IOException {
		List<BrainfuckChar> l = new ArrayList<BrainfuckChar>();
		BrainfuckSourceReader codeReader = new BrainfuckSourceReader(filePath);
		Stack<Integer> braceIndices = new Stack<Integer>();
		while(codeReader.hasNext()) {
			BrainfuckChar c = codeReader.next();
			if(c == BrainfuckChar.OPEN)
				braceIndices.add(l.size());
			else if(c == BrainfuckChar.CLOSE) {
				match.put(braceIndices.peek(), l.size());
				match.put(l.size(), braceIndices.pop());
			}
			l.add(c);
		}
		code = new BrainfuckChar[l.size()];
		code = l.toArray(code);
	}
	public void execute() throws IOException {
		while(codeIndex < code.length) {
			BrainfuckChar c = code[codeIndex];
			if(c == BrainfuckChar.SHIFT_RIGHT)
				ribbon.shiftRight();
			else if(c == BrainfuckChar.SHIFT_LEFT)
				ribbon.shiftLeft();
			else if(c == BrainfuckChar.INCREASE)
				ribbon.increase();
			else if(c == BrainfuckChar.DECREASE)
				ribbon.decrease();
			else if(c == BrainfuckChar.OUTPUT)
				System.out.print(ribbon.get());
			else if(c == BrainfuckChar.INPUT)
				ribbon.set(BrainfuckSystem.in.next());
			else if(c == BrainfuckChar.OPEN) {
				if(ribbon.get() == 0)
					codeIndex = match.get(codeIndex);
			} else if(c == BrainfuckChar.CLOSE) {
				if(ribbon.get() > 0)
					codeIndex = match.get(codeIndex);
			}
			codeIndex++;
		}
	}
	public static void main(String[] args) throws IOException {
		if(args.length < 1)
			System.err.println("Pass the brainfuck file path as the argument");
		else
			new BrainfuckInterpreter(args[0]).execute();
	}
}
